package com.meiyuetao.myt.crawl.filter;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;

import lab.s2jh.core.pagination.GroupPropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter;
import lab.s2jh.core.pagination.PropertyFilter.MatchType;
import lab.s2jh.crawl.filter.AbstractParseFilter;

import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.xpath.XPathAPI;
import org.joda.time.DateTime;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.Sort.Direction;
import org.springframework.util.Assert;
import org.w3c.dom.Node;

import com.gargoylesoftware.htmlunit.html.DomElement;
import com.gargoylesoftware.htmlunit.html.HtmlElement;
import com.gargoylesoftware.htmlunit.html.HtmlPage;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.meiyuetao.myt.crawl.entity.CrawlBizMetadata;
import com.meiyuetao.myt.crawl.entity.ParseCommodity;
import com.meiyuetao.myt.crawl.entity.ParsePropTrack;
import com.meiyuetao.myt.crawl.service.ParseCommodityService;
import com.meiyuetao.myt.crawl.service.ParsePropTrackService;
import com.meiyuetao.myt.md.service.CommodityCommentService;
import com.meiyuetao.myt.md.service.CommodityService;

public abstract class AbstractCommodityParseFilter extends AbstractParseFilter {

    private static final Logger logger = LoggerFactory.getLogger(AbstractCommodityParseFilter.class);

    private static final String[] SENSITIVE_WORD = { "买家", " 卖家", "店主", "bgoimg", "京东", "jingdong", "360buy", "jd.com", "jd", "tmall", "天猫", "苏宁", "suning", "redbaby", "ymatou",
            "tbcdn", "taobao", "淘宝", "aliyuncdn", "alicdn", "红孩子", "洋码头", "幸孕", "xyb2c", "易购", "旗舰店" };

    protected ParsePropTrackService parsePropTrackService;
    protected ParseCommodityService parseCommodityService;
    protected CommodityService commodityService;
    protected CommodityCommentService commodityCommentService;

    /**
     * 处理不同src图片属性格式，返回统一格式的http格式的图片URL
     * 
     * @param url
     * @param imgSrc
     * @return
     */
    protected String parseImgSrc(String url, String imgSrc) {
        if (StringUtils.isBlank(imgSrc)) {
            return null;
        }
        imgSrc = imgSrc.trim();
        // 去掉链接最后的#号
        imgSrc = StringUtils.substringBefore(imgSrc, "#");
        if (imgSrc.startsWith("http")) {
            return imgSrc;
        } else if (imgSrc.startsWith("/")) {
            if (url.indexOf(".com") > -1) {
                return StringUtils.substringBefore(url, ".com/") + ".com" + imgSrc;
            } else if (url.indexOf(".net") > -1) {
                return StringUtils.substringBefore(url, ".net/") + ".net" + imgSrc;
            } else {
                throw new RuntimeException("Undefined site domain suffix");
            }
        } else {
            return StringUtils.substringBeforeLast(url, "/") + "/" + imgSrc;
        }
    }

    protected String parseTitle(HtmlPage htmlPage, String... xpaths) {
        String title;
        for (String xpath : xpaths) {
            HtmlElement titleNode = htmlPage.getFirstByXPath(xpath);
            if (titleNode == null) {
                return null;
            }
            title = titleNode.asText();

            if (StringUtils.isNotBlank(title)) {
                return title;
            }
        }
        return null;
    }

    protected void parseSalePrice(ParseCommodity parseCommodity, HtmlPage htmlPage, String xpath, String proPath) {
        try {
            // 销售价格属性处理

            HtmlElement salePriceNode = htmlPage.getFirstByXPath(proPath);
            String salePrice = "";
            if (salePriceNode == null) {
                salePriceNode = htmlPage.getFirstByXPath(proPath);
            }
            if (salePriceNode != null) {
                salePrice = salePriceNode.asText();
            }
            salePrice = cleanInvisibleChar(salePrice);
            logger.debug("Price for url: {} is {}", parseCommodity.getBaseUrl(), salePrice);
            if (StringUtils.isNotBlank(salePrice)) {
                BigDecimal salePriceDecimal = null;
                char c = salePrice.trim().charAt(0);
                if (c > '9' || c < '0') {
                    salePriceDecimal = new BigDecimal(salePrice.substring(1, salePrice.length()));
                } else {
                    salePriceDecimal = new BigDecimal(salePrice);
                }

                // 判断如果以前没有存储价格或价格有变动,则写入属性变化跟踪表
                if (true) {
                    if (parseCommodity.getSalePrice() == null || !parseCommodity.getSalePrice().equals(salePriceDecimal)) {
                        Long now = new Date().getTime();
                        ParsePropTrack parsePropTrack = new ParsePropTrack(parseCommodity.getBaseUrl(), CrawlBizMetadata.COMMODITY_PRICES + "." + now);
                        parsePropTrack.setOrderRank(String.valueOf(now));
                        parsePropTrack.setPropGroup(CrawlBizMetadata.COMMODITY_PRICES);
                        parsePropTrack.setPropValue(salePrice);
                        parsePropTrack.setPropLabel("商品价格");
                        parsePropTrack.setUid(parseCommodity.getBaseUrl() + ":" + parsePropTrack.getPropKey()
                                + (StringUtils.isNotBlank(parsePropTrack.getPropSubKey()) ? ":" + parsePropTrack.getPropSubKey() : ""));
                        parsePropTrackService.save(parsePropTrack);
                    }
                }
                parseCommodity.setSalePrice(salePriceDecimal);
                return;
            }
            parseCommodity.setStockState("下架");
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            parseCommodity.addSysMemo("解析商品价格异常:" + e.getMessage());
        }
    }

    /**
     * 清除无关的不可见空白字符
     * 
     * @param str
     * @return
     */
    protected String cleanInvisibleChar(String str) {
        str = StringUtils.remove(str, (char) 160);
        str = StringUtils.remove(str, " ");
        str = StringUtils.remove(str, "\r");
        str = StringUtils.remove(str, "\n");
        str = StringUtils.remove(str, "\t");
        str = StringUtils.remove(str, "\\s*");
        return str;
    }

    protected static String getXPathValue(Node doc, String xpath) {
        try {
            if (doc instanceof DomElement) {
                DomElement domElement = (DomElement) doc;
                DomElement xpathNode = domElement.getFirstByXPath(xpath);
                if (xpathNode == null) {
                    logger.warn("No node found for xpath: " + xpath);
                    return "";
                } else {
                    return xpathNode.asText();
                }
            } else {
                Node node = XPathAPI.selectSingleNode(doc, xpath);
                if (node == null) {
                    logger.warn("No node found for xpath: " + xpath);
                    return "";
                } else {
                    return node.getTextContent().trim();
                }
            }
        } catch (Exception e) {
            throw new RuntimeException("Failed xpath: " + xpath, e);
        }
    }

    public Boolean isContainSensitiveWord(String content) {
        Boolean flag = false;
        for (String s : SENSITIVE_WORD) {
            if (content.contains(s)) {
                flag = true;
                break;
            }
        }
        if (content.contains("年") && content.contains("月")) {
            flag = true;
        }
        return flag;
    }

    @SuppressWarnings("deprecation")
    public Date createBoughtTime(Date publishTime) {
        DateTime publishTimeJoda = new DateTime(publishTime);
        Date boughtTime = publishTimeJoda.minusDays(new Random().nextInt(60) + 30).toDate();
        boughtTime.setHours(new Random().nextInt(15) + 7);
        boughtTime.setMinutes(new Random().nextInt(59));
        boughtTime.setSeconds(new Random().nextInt(59));
        return boughtTime;
    }

    public void parseWindowImgs(ParseCommodity parseCommodity, HtmlPage htmlPage, String xpath, String faultPath, String lazySrc) {
        try {
            // 橱窗图
            Set<String> removeImgSrcUrls = removeImgSrcUrls();
            Set<String> imgSet = Sets.newHashSet();
            String url = parseCommodity.getBaseUrl();
            List<?> windowImgNodes = htmlPage.getByXPath(xpath);
            if (windowImgNodes == null || windowImgNodes.size() == 0) {
                windowImgNodes = htmlPage.getByXPath(faultPath);

            }
            if (windowImgNodes == null || windowImgNodes.size() == 0) {
                parseCommodity.addSysMemo("未解析到商品橱窗图");
            } else {
                GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
                groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "baseUrl", url));
                groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "propGroup", CrawlBizMetadata.COMMODITY_WINDOW_IMGS));
                List<ParsePropTrack> winImgsPropTracks = parsePropTrackService.findByFilters(groupPropertyFilter, new org.springframework.data.domain.Sort(Direction.DESC,
                        "fetchTime"));
                for (int i = 0; i < windowImgNodes.size(); i++) {
                    HtmlElement node = (HtmlElement) windowImgNodes.get(i);
                    String src = parseImgSrc(url, node.getAttribute(lazySrc));
                    // 有些商品描述没有采用LazyLoad机制,则直接取src值,如:http://www.suning.com/emall/prd_10052_10051_-7_5017367_.html
                    if (StringUtils.isBlank(src)) {
                        src = parseImgSrc(url, node.getAttribute("src"));
                    }
                    // 特殊处理jd橱窗图
                    src = src.replaceAll("/n5/", "/n1/");
                    // 特殊处理：http://detail.tmall.hk/hk/item.htm?spm=a1z10.5.w4011-3029558042.92.kywdZ0&id=26287932604&rn=c41f122437876ca30dd5e28058c6453e
                    // http://gi2.md.alicdn.com/imgextra/i2/1737789119/T2cZAyXl0XXXXXXXXX_!!1737789119.jpg_60x60.jpg
                    src = src.replaceAll("_60x60.jpg", "").replaceAll("_60x60q90.jpg", "");

                    if (removeImgSrcUrls != null && removeImgSrcUrls.contains(src)) {
                        continue;
                    }

                    // 处理有可能一个页面多次引用同一个src图片
                    if (imgSet.contains(src)) {
                        continue;
                    } else {
                        imgSet.add(src);
                    }

                    ParsePropTrack parsePropTrack = null;
                    for (ParsePropTrack img : winImgsPropTracks) {
                        if (img.getPropKey().equals(src)) {
                            parsePropTrack = img;
                            break;
                        }
                    }
                    if (parsePropTrack == null) {
                        parsePropTrack = new ParsePropTrack(parseCommodity.getBaseUrl(), src);
                        String imgUrl = uploadImg(src);
                        // 上传图片为空置情况处理，如图片地址404不存在等,此时无需保存记录
                        if (StringUtils.isNotBlank(imgUrl)) {
                            parsePropTrack.setPropValue(imgUrl);
                            parsePropTrack.setOrderRank(String.valueOf(i));
                            parsePropTrack.setPropGroup(CrawlBizMetadata.COMMODITY_WINDOW_IMGS);
                            parsePropTrack.setPropKey(src);
                            parsePropTrack.setPropLabel("橱窗图片");
                            parsePropTrack.setUid(url + ":" + parsePropTrack.getPropKey()
                                    + (StringUtils.isNotBlank(parsePropTrack.getPropSubKey()) ? ":" + parsePropTrack.getPropSubKey() : ""));
                            parsePropTrackService.save(parsePropTrack);
                            winImgsPropTracks.add(parsePropTrack);
                        }
                    }
                }
                parseCommodity.setWinImgNum(winImgsPropTracks.size());
                if (parseCommodity.getWinImgNum() == 0) {
                    parseCommodity.addSysMemo("实际解析到商品橱窗图数量为0");
                }
            }
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            parseCommodity.addSysMemo("解析商品橱窗图异常:" + e.getMessage());
        }
    }

    /**
     * 描述部分在各实际页面对象预处理回调逻辑 子类根据需要进行覆写即可
     * 
     * @param doc
     */
    protected void parseDescriptionPreProcess(HtmlPage htmlPage) throws Exception {
    }

    protected Set<String> removeImgSrcUrls() {
        return null;
    }

    public void parseDescription(ParseCommodity parseCommodity, HtmlPage htmlPage, String xpathDescription, String xpathDescriptionLazyImgs, String lazySrc,
            String[] ALERT_DOMAIN_INFOS) {
        try {
            parseDescriptionPreProcess(htmlPage);

            List<?> nodeListP = htmlPage.getByXPath("//P");
            for (int i = 0; i < nodeListP.size(); i++) {
                HtmlElement node = (HtmlElement) nodeListP.get(i);
                node.removeAttribute("style");
            }
            List<?> nodeListSpan = htmlPage.getByXPath("//SPAN");
            for (int i = 0; i < nodeListSpan.size(); i++) {
                HtmlElement node = (HtmlElement) nodeListSpan.get(i);
                node.removeAttribute("style");
            }
            List<?> nodeListFont = htmlPage.getByXPath("//FONT");
            for (int i = 0; i < nodeListFont.size(); i++) {
                HtmlElement node = (HtmlElement) nodeListFont.get(i);
                node.removeAttribute("color");
            }
            Set<String> removeImgSrcUrls = removeImgSrcUrls();
            Set<String> imgSet = Sets.newHashSet();
            String url = parseCommodity.getBaseUrl();
            // 商品描述
            if (xpathDescriptionLazyImgs != null) {
                List<?> lazyImgNodes = htmlPage.getByXPath(xpathDescriptionLazyImgs);
                GroupPropertyFilter groupPropertyFilter = GroupPropertyFilter.buildDefaultAndGroupFilter();
                groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "baseUrl", url));
                groupPropertyFilter.append(new PropertyFilter(MatchType.EQ, "propGroup", CrawlBizMetadata.COMMODITY_DESCRIPTION_IMGS));
                List<ParsePropTrack> descImgsPropTracks = parsePropTrackService.findByFilters(groupPropertyFilter, new org.springframework.data.domain.Sort(Direction.DESC,
                        "fetchTime"));
                for (int i = 0; i < lazyImgNodes.size(); i++) {
                    HtmlElement node = (HtmlElement) lazyImgNodes.get(i);
                    String src = node.getAttribute(lazySrc);
                    // 有些商品描述没有采用LazyLoad机制,则直接取src值,如:http://www.suning.com/emall/prd_10052_10051_-7_5017367_.html
                    if (StringUtils.isBlank(src)) {
                        src = node.getAttribute("src");
                    }
                    Assert.isTrue(StringUtils.isNotBlank(src));
                    src = parseImgSrc(url, src);
                    // 指定无需处理的图片
                    if (removeImgSrcUrls != null && removeImgSrcUrls.contains(src)) {
                        node.getParentNode().removeChild(node);
                        continue;
                    }

                    // 处理有可能一个页面多次引用同一个src图片
                    if (imgSet.contains(src)) {
                        continue;
                    } else {
                        imgSet.add(src);
                    }
                    ParsePropTrack parsePropTrack = null;
                    for (ParsePropTrack img : descImgsPropTracks) {
                        if (img.getPropKey().equals(src)) {
                            parsePropTrack = img;
                            break;
                        }
                    }

                    if (parsePropTrack == null) {
                        parsePropTrack = new ParsePropTrack(url, src);
                        parsePropTrack.setOrderRank(String.valueOf(i));
                        String imgUrl = uploadImg(src);
                        // 上传图片为空置情况处理，如图片地址404不存在等,此时无需保存记录,删除当前img节点
                        if (StringUtils.isBlank(imgUrl)) {
                            node.getParentNode().removeChild(node);
                            continue;
                        }
                        parsePropTrack.setPropValue(imgUrl);
                        parsePropTrack.setPropGroup(CrawlBizMetadata.COMMODITY_DESCRIPTION_IMGS);
                        parsePropTrack.setPropLabel("描述图片");
                        parsePropTrack.setUid(url + ":" + parsePropTrack.getPropKey()
                                + (StringUtils.isNotBlank(parsePropTrack.getPropSubKey()) ? ":" + parsePropTrack.getPropSubKey() : ""));
                        parsePropTrackService.save(parsePropTrack);
                        descImgsPropTracks.add(parsePropTrack);
                    }
                    String imgWidth = node.getAttribute("width");
                    if (StringUtils.isNotBlank(imgWidth)) {
                        // 把原有宽度以非标准属性记录下来
                        node.setAttribute("xwidth", imgWidth);
                        node.removeAttribute("width");
                    }

                    node.removeAttribute("onload");
                    node.removeAttribute("alt");
                    node.removeAttribute(lazySrc);
                    node.removeAttribute("height");
                    node.removeAttribute("class");
                    node.removeAttribute("style");
                    node.setAttribute("src", parsePropTrack.getPropValue().toString());
                }
                parseCommodity.setDescImgNum(descImgsPropTracks.size());
            }
            HtmlElement descriptionNode = htmlPage.getFirstByXPath(xpathDescription);
            if (descriptionNode != null) {
                parseCommodity.addDescription(descriptionNode.asXml());
            } else {
                parseCommodity.addSysMemo("未解析到商品描述");
            }

            // 额外检查解析的描述部分是否还包含相关域名信息,记录到备注里面以便进一步排查
            if (ALERT_DOMAIN_INFOS != null) {
                for (String domain : ALERT_DOMAIN_INFOS) {
                    if (parseCommodity.getDescription().indexOf(domain) > -1) {
                        parseCommodity.addSysMemo("描述内容中包含第三方域名信息需排查处理:" + StringUtils.join(ALERT_DOMAIN_INFOS, ","));
                    }
                }
            }

            /*
             * //更新用于Solr索引的文本 String indexText = parseCommodity.getTitle(); if
             * (descriptionNode != null) { indexText +=
             * descriptionNode.toString(); } Parse oldParse =
             * parseResult.get(new Text(url)); return
             * ParseResult.createParseResult(parseCommodity.getBaseUrl(), new
             * ParseImpl(indexText, oldParse.getData()));
             */
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            parseCommodity.addSysMemo("解析商品描述异常:" + e.getMessage());
        }

    }

    public void parseSalePrompt(ParseCommodity parseCommodity, HtmlPage htmlPage, String xpath) {
        try {
            // 促销口号
            HtmlElement salePromptNode = htmlPage.getFirstByXPath(xpath);
            String salePrompt = null;
            if (salePromptNode != null) {
                salePrompt = salePromptNode.asText();
            }

            if (StringUtils.isNotBlank(salePrompt)) {
                salePrompt = cleanInvisibleChar(salePrompt);
            }
            // 判断并写入属性变化跟踪表
            if (true && StringUtils.isNotBlank(salePrompt)) {
                if (parseCommodity.getSalePrompt() == null || !salePrompt.equals(parseCommodity.getSalePrompt())) {
                    Long now = new Date().getTime();
                    ParsePropTrack parsePropTrack = new ParsePropTrack(parseCommodity.getBaseUrl(), CrawlBizMetadata.COMMODITY_SALE_PROMPTS + "." + now);
                    parsePropTrack.setOrderRank(String.valueOf(now));
                    parsePropTrack.setPropGroup(CrawlBizMetadata.COMMODITY_SALE_PROMPTS);
                    parsePropTrack.setPropValue(salePrompt);
                    parsePropTrack.setPropLabel("促销口号");
                    parsePropTrack.setUid(parseCommodity.getBaseUrl() + ":" + parsePropTrack.getPropKey()
                            + (StringUtils.isNotBlank(parsePropTrack.getPropSubKey()) ? ":" + parsePropTrack.getPropSubKey() : ""));
                    parsePropTrackService.save(parsePropTrack);
                }
                parseCommodity.setSalePrompt(salePrompt);
            }

        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            parseCommodity.addSysMemo("解析商品促销口号异常:" + e.getMessage());
        }
    }

    public void parseSaleStock(ParseCommodity parseCommodity, HtmlPage htmlPage, String... xpaths) {
        try {
            // 库存属性处理
            for (String xpath : xpaths) {
                HtmlElement stockStateNode = htmlPage.getFirstByXPath(xpath);
                String stockState = null;
                if (stockStateNode != null) {
                    stockState = stockStateNode.asText();
                }
                if (StringUtils.isNotBlank(stockState)) {
                    stockState = cleanInvisibleChar(stockState);
                }

                // 判断并写入属性变化跟踪表
                if (true && StringUtils.isNotBlank(stockState)) {
                    if (parseCommodity.getStockState() == null || !stockState.equals(parseCommodity.getStockState())) {
                        Long now = new Date().getTime();
                        ParsePropTrack parsePropTrack = new ParsePropTrack(parseCommodity.getBaseUrl(), CrawlBizMetadata.COMMODITY_STOCKS + "." + now);
                        parsePropTrack.setOrderRank(String.valueOf(now));
                        parsePropTrack.setPropGroup(CrawlBizMetadata.COMMODITY_STOCKS);
                        parsePropTrack.setPropValue(stockState);
                        parsePropTrack.setPropLabel("商品库存");
                        parsePropTrack.setUid(parseCommodity.getBaseUrl() + ":" + parsePropTrack.getPropKey()
                                + (StringUtils.isNotBlank(parsePropTrack.getPropSubKey()) ? ":" + parsePropTrack.getPropSubKey() : ""));
                        parsePropTrackService.save(parsePropTrack);
                    }
                    parseCommodity.setStockState(stockState);
                }

            }
        } catch (Exception e) {
            logger.warn(e.getMessage(), e);
            parseCommodity.addSysMemo("解析商品库存异常:" + e.getMessage());
        }
    }

    private static Map<String, String> cachedImgsMap = Maps.newHashMap();

    protected String uploadImg(String src) {
        try {

            Assert.isTrue(StringUtils.isNotBlank(src));

            // 过滤太长的异常图片SRC URL
            if (src.length() > 1024) {
                return "";
            }
            // String url =
            // "http://img2.iyoubox.com/PutUrl.aspx?ShowWater=0&FileUrl=" +
            // URLEncoder.encode(src, "UTF-8");
            String url = "http://img.iyoubox.com/PutLocalFile.aspx?showWater=0&file=" + URLEncoder.encode(src, "UTF-8");
            String cachedData = cachedImgsMap.get(url);
            if (cachedData != null) {
                return cachedData;
            }
            logger.debug("Uploading img : {}", url);
            String result;
            HttpPost httpPost = new HttpPost(url);
            HttpClient httpClient = new DefaultHttpClient();
            InputStream inputStream = null;

            // 使用http客户端发送一个请求
            HttpResponse httpResponse = httpClient.execute(httpPost);
            HttpEntity httpEntity = httpResponse.getEntity();
            inputStream = httpEntity.getContent();
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            result = "";
            String line = "";
            while ((line = br.readLine()) != null) {
                result = result + line;
            }
            if (result.startsWith("1+")) {
                String md5url = "http://img.iyoubox.com/GetFileByCode.aspx?code=" + result.substring(2, result.length());
                cachedImgsMap.put(url, md5url);
                return md5url;
            } else {
                logger.warn(result);
            }
        } catch (Exception e) {
            logger.error(e.getMessage(), e);
        }
        return "";
    }

    public abstract Map<String, Object> parseSimpleData(String url);

    public ParsePropTrackService getParsePropTrackService() {
        return parsePropTrackService;
    }

    public void setParsePropTrackService(ParsePropTrackService parsePropTrackService) {
        this.parsePropTrackService = parsePropTrackService;
    }

    public ParseCommodityService getParseCommodityService() {
        return parseCommodityService;
    }

    public void setParseCommodityService(ParseCommodityService parseCommodityService) {
        this.parseCommodityService = parseCommodityService;
    }

    public CommodityService getCommodityService() {
        return commodityService;
    }

    public void setCommodityService(CommodityService commodityService) {
        this.commodityService = commodityService;
    }

    public CommodityCommentService getCommodityCommentService() {
        return commodityCommentService;
    }

    public void setCommodityCommentService(CommodityCommentService commodityCommentService) {
        this.commodityCommentService = commodityCommentService;
    }

}
